package com.demo2do.fms.appointment.service;

import java.io.File;
import java.io.Writer;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.output.FileWriterWithEncoding;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dao;
import com.demo2do.fms.appointment.dao.DriverCostAppointmentDao;
import com.demo2do.fms.appointment.dao.DriverMileageAppointmentDao;
import com.demo2do.fms.appointment.dao.FmsJdbcSupport;
import com.demo2do.fms.appointment.dao.TransportRevenueAppointmentDao;
import com.demo2do.fms.appointment.dao.UserDao;
import com.demo2do.fms.appointment.dao.VehicleMileageAppointmentDao;
import com.demo2do.fms.appointment.entity.DriverAccumulatedMileageSearch;
import com.demo2do.fms.appointment.entity.DriverCostSearch;
import com.demo2do.fms.appointment.entity.TransportRevenueScheduleSearch;
import com.demo2do.fms.appointment.entity.VehicleAccumulatedMileageSearch;
import com.demo2do.fms.appointment.utils.CsvUtils;
import com.demo2do.fms.entity.report.DriverCostAppointment;
import com.demo2do.fms.entity.report.DriverMileageAppointment;
import com.demo2do.fms.entity.report.AppointmentStatus;
import com.demo2do.fms.entity.report.TransportRevenueAppointment;
import com.demo2do.fms.entity.report.VehicleMileageAppointment;

/**
 *
 * @author Ark
 *
 */
@Service("appointmentService")
public class AppointmentServiceImpl implements AppointmentService {
    
    private static final Logger logger = LoggerFactory.getLogger(AppointmentServiceImpl.class);

    @Value("#{config['appointment.page.size']}")
    private Integer pageSize;
    
    @Value("#{config['appointment.csv.path']}")
    private String csvPath;
    
    @Value("#{config['appointment.csv.url']}")
    private String csvUrl;
    
    @Autowired
    private FmsJdbcSupport fmsJdbcSupport;
    
    @Autowired
    private GenericDaoSupport genericDaoSupport;
    
    @Dao
    private VehicleMileageAppointmentDao vehicleMileageAppointmentDao;
    
    @Dao
    private DriverMileageAppointmentDao driverMileageAppointmentDao;
    
    @Dao
    private DriverCostAppointmentDao driverCostAppointmentDao;
    
    @Dao
    private TransportRevenueAppointmentDao transportRevenueAppointmentDao;
    
    @Dao
    private UserDao userDao;
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.appointment.service.AppointmentService#listVehicleMileage()
     */
    public List<VehicleMileageAppointment> listVehicleMileage() {
        return vehicleMileageAppointmentDao.list(AppointmentStatus.APPOINTED);
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.scheduler.service.AppointmentService#exportVehicleMileage()
     */
    public void exportVehicleMileage(VehicleMileageAppointment appointment) {
        
        Long operator = userDao.get("super").getId();
        
        try {
            
            // 1 start handle appointment
            genericDaoSupport.update(appointment.start(operator));
            
            // 2 search by page
            VehicleAccumulatedMileageSearch search = new VehicleAccumulatedMileageSearch(appointment);
            Map<String, Object> parameters = search.buildParameters();
            
            int totals = fmsJdbcSupport.queryForInt(search.buildCountTemplate(), parameters);
            int totalPage = (totals + (pageSize - 1)) / pageSize;
            
            String[] titles = {"运输公司", "驳运车车牌", "调度指令组号", "出发地", "目的地", "行驶公里数", "重载公里数", "重载率", "空载公里数", "空载率", "车队", "路桥费", "油费", "其他费用", "内部加油量"};
            
            for (int page = 0; page < totalPage; page++) {

                // 3. construct result 
                Integer beginIndex = page * pageSize + 1;
                search.setBeginIndex(beginIndex);
                
                Integer endIndex = (page + 1) * pageSize;
                search.setEndIndex(endIndex);
                
                List<String[]> lines = new LinkedList<String[]>();
                if (page == 0) {
                    lines.add(titles);
                }
                List<String[]> result = fmsJdbcSupport.queryForList(search.buildSentenceTemplate(), parameters, search.buildRowMapper());
                lines.addAll(result);

                // 4. write to csv_file
                String savePath = csvPath + appointment.getCode() + ".csv";
                File csvFile = new File(savePath);
                Writer writer = new FileWriterWithEncoding(csvFile, "GBK", true);
                CsvUtils.write(lines, writer);
                
            }
            
            // 5. handle appointment success
            String saveUrl = csvUrl + appointment.getCode() + ".csv";
            genericDaoSupport.update(appointment.success(saveUrl, operator));
            
        } catch (Exception e) {
            genericDaoSupport.update(appointment.fail(operator));
            logger.error("#exportVehicleMileage() - code=[{}] occur exception=[{}]", appointment.getCode(), e);
        }
            
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.appointment.service.AppointmentService#listDriverMileage()
     */
    public List<DriverMileageAppointment> listDriverMileage() {
        return driverMileageAppointmentDao.list(AppointmentStatus.APPOINTED);
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.appointment.service.AppointmentService#exportDriverMileage(com.demo2do.fms.entity.report.DriverMileageAppointment)
     */
    public void exportDriverMileage(DriverMileageAppointment appointment) {
        
        Long operator = userDao.get("super").getId();
        
        try {
            
            // 2.1 start handle appointment
            genericDaoSupport.update(appointment.start(operator));
            
            // 2.2 search by page
            DriverAccumulatedMileageSearch search = new DriverAccumulatedMileageSearch(appointment);
            Map<String, Object> parameters = search.buildParameters();
            
            int totals = fmsJdbcSupport.queryForInt(search.buildCountTemplate(), parameters);
            int totalPage = (totals + (pageSize - 1)) / pageSize;
            
            String[] titles = {"驾驶员", "公司名称", "内部调度指令", "调度日期", "驳运车车牌", "起始地", "目的地", "重载公里数", "空载公里数", "行驶公里数", "重载工资", "空载工资", "总工资"};
            
            for (int page = 0; page < totalPage; page++) {

                // 3. construct result 
                Integer beginIndex = page * pageSize + 1;
                search.setBeginIndex(beginIndex);
                
                Integer endIndex = (page + 1) * pageSize;
                search.setEndIndex(endIndex);
                
                List<String[]> lines = new LinkedList<String[]>();
                if (page == 0) {
                    lines.add(titles);
                }
                List<String[]> result = fmsJdbcSupport.queryForList(search.buildSentenceTemplate(), parameters, search.buildRowMapper());
                lines.addAll(result);

                // 4. write to csv_file
                String savePath = csvPath + appointment.getCode() + ".csv";
                File csvFile = new File(savePath);
                Writer writer = new FileWriterWithEncoding(csvFile, "GBK", true);
                CsvUtils.write(lines, writer);
                
            }
            
            // 5. handle appointment success
            String saveUrl = csvUrl + appointment.getCode() + ".csv";
            genericDaoSupport.update(appointment.success(saveUrl, operator));
            
        } catch (Exception e) {
            genericDaoSupport.update(appointment.fail(operator));
            logger.error("#exportDriverMileage() - code=[{}] occur exception=[{}]", appointment.getCode(), e);
        }
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.appointment.service.AppointmentService#listTransportRevenue()
     */
    public List<TransportRevenueAppointment> listTransportRevenue() {
        return transportRevenueAppointmentDao.list(AppointmentStatus.APPOINTED);
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.appointment.service.AppointmentService#exportTransportRevenue()
     */
    public void exportTransportRevenue(TransportRevenueAppointment appointment) {
        
        // 1. list need handle appointment
        Long operator = userDao.get("super").getId();
        
        try {
            
            // 2.1 start handle appointment
            genericDaoSupport.update(appointment.start(operator));
            
            // 2.2 search by page
            TransportRevenueScheduleSearch search = new TransportRevenueScheduleSearch(appointment);
            Map<String, Object> parameters = search.buildParameters();
            
            int totals = fmsJdbcSupport.queryForInt(search.buildCountTemplate(), parameters);
            int totalPage = (totals + (pageSize - 1)) / pageSize;
            
            String[] titles = {"驳运车", "订单号", "调度单号", "派车单号", "预计发车时间", "调度指令时间", "运输方式", "委托方", "承运方", "最终客户", "制造商", "出发地", "目的地", "回单日期", 
                    "可结算标识", "总收入", "费率", "结算公里数", "是否暂估", "是否开票", "开票日期", "是否销单", "车型大类", "颜色", "VIN码", "承接车队", "外结费用", "外结单价", "外结公里数", "外结是否暂估", 
                    "FMS公司代码", "原始收入订单", "VIN码", "调度单号", "运输成本", "运输收入", "SESSION_ID"};
            
            for (int page = 0; page < totalPage; page++) {

                // 3. construct result 
                Integer beginIndex = page * pageSize + 1;
                search.setBeginIndex(beginIndex);
                
                Integer endIndex = (page + 1) * pageSize;
                search.setEndIndex(endIndex);
                
                List<String[]> lines = new LinkedList<String[]>();
                if (page == 0) {
                    lines.add(titles);
                }
                List<String[]> result = fmsJdbcSupport.queryForList(search.buildSentenceTemplate(), parameters, search.buildRowMapper());
                lines.addAll(result);

                // 4. write to csv_file
                String savePath = csvPath + appointment.getCode() + ".csv";
                File csvFile = new File(savePath);
                Writer writer = new FileWriterWithEncoding(csvFile, "GBK", true);
                CsvUtils.write(lines, writer);
                
            }
            
            // 5. handle appointment success
            String saveUrl = csvUrl + appointment.getCode() + ".csv";
            genericDaoSupport.update(appointment.success(saveUrl, operator));
            
        } catch (Exception e) {
            genericDaoSupport.update(appointment.fail(operator));
            logger.error("#exportDriverMileage() - code=[{}] occur exception=[{}]", appointment.getCode(), e);
        }
        
    }

    /* (non-Javadoc)
     * @see com.demo2do.fms.appointment.service.AppointmentService#listDriverCost()
     */
    public List<DriverCostAppointment> listDriverCost() {
        return driverCostAppointmentDao.list(AppointmentStatus.APPOINTED);
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.appointment.service.AppointmentService#exportDriverCost()
     */
    public void exportDriverCost(DriverCostAppointment appointment) {
    
        // 1. list need handle appointment
        Long operator = userDao.get("super").getId();
        
        try {
            
            // 2.1 start handle appointment
            genericDaoSupport.update(appointment.start(operator));
            
            // 2.2 search by page
            DriverCostSearch search = new DriverCostSearch(appointment);
            Map<String, Object> parameters = search.buildParameters();
            
            int totals = fmsJdbcSupport.queryForInt(search.buildCountTemplate(), parameters);
            int totalPage = (totals + (pageSize - 1)) / pageSize;
            
            String[] titles = {"驳运车号", "派车单号", "调度指令组号", "主驾姓名", "第一副驾驶员", "报销日期", "报销单号", "起始装卸地", "目的装卸地", "商品车数量", "商品车明细",
                    "行驶公里数", "路桥费", "外部油费", "内部加油贴现", "交通费（夜进夜出）", "广告费", "短驳补贴", "提车费用", "交车费用", "冬季油差补贴", "通讯费补贴", "延伸公里数",
                    "多点装车补贴", "多点卸车补贴", "银行取款手续费", "高速补贴", "停车补贴", "带车补贴", "其他费用", "油价补贴", "油耗补贴", "洗车费", "住宿补贴", "摆渡费", "轮胎补贴（冻结）",
                    "副驾带车费用", "线路包干费", "制单人", "报销人"};
            
            for (int page = 0; page < totalPage; page++) {

                // 3. construct result 
                Integer beginIndex = page * pageSize + 1;
                search.setBeginIndex(beginIndex);
                
                Integer endIndex = (page + 1) * pageSize;
                search.setEndIndex(endIndex);
                
                List<String[]> lines = new LinkedList<String[]>();
                if (page == 0) {
                    lines.add(titles);
                }
                List<String[]> result = fmsJdbcSupport.queryForList(search.buildSentenceTemplate(), parameters, search.buildRowMapper());
                lines.addAll(result);

                // 4. write to csv_file
                String savePath = csvPath + appointment.getCode() + ".csv";
                File csvFile = new File(savePath);
                Writer writer = new FileWriterWithEncoding(csvFile, "GBK", true);
                CsvUtils.write(lines, writer);
                
            }
            
            // 5. handle appointment success
            String saveUrl = csvUrl + appointment.getCode() + ".csv";
            genericDaoSupport.update(appointment.success(saveUrl, operator));
            
        } catch (Exception e) {
            genericDaoSupport.update(appointment.fail(operator));
            logger.error("#exportDriverMileage() - code=[{}] occur exception=[{}]", appointment.getCode(), e);
        }
        
    }
    
}
